package DecisionMaker;

import Parser.*;
import Fuzzy.*;
import GUI.*;
import java.util.Vector;

public class DecisionMakerClass {
    //attributen
    private KBParser parser;
    private GUI.Process process;
    private MakeFuzzy fuzzy;
    private Defuzzy defuzzy;
    public double variable;
    private Vector fuzzyValues;
    private Vector tempVector;
    private Vector temp;
    private boolean printProgress;

    //constructor
	public DecisionMakerClass(KBParser prsr, GUI.Process prcss)
	{
        parser = prsr;
        fuzzy = new MakeFuzzy(parser);
        defuzzy = new Defuzzy(parser);
        process = prcss;
        temp = new Vector();
        tempVector = new Vector();

        // messaging aan / uit
        printProgress = false;
    }

    //methods

    private void analyseRule(String rule) {

        Rule regel = new Rule(rule, fuzzyValues);
        // messaging hetzelfde als super
        regel.printProgress = printProgress;
        String returnValue = regel.solvePremise();
        Vector nw = regel.solveConclusion();
        // zet de decissions aan t einde van de vector.
        for (int x = 0; x < nw.size(); x++) {
            temp.add(nw.elementAt(x));
        }

        // zet de decission in de vector
        temp.add(returnValue.toString());
    }

    private Vector orderVector(Vector unorderedVector) {

        // vector aanmaken(gesorteerd)
        Vector orderedVector = new Vector();
        boolean temp = false;
        int tempInt = 0;

        if(unorderedVector.size() < 3){
            return null;
        }
        // save eerste universe name
        orderedVector.add(unorderedVector.elementAt(0));
        // save eerste variable name
        orderedVector.add(unorderedVector.elementAt(1));
        // save eerste value
        orderedVector.add(unorderedVector.elementAt(2));

        for(int x = 3 ; x < unorderedVector.size() ; x+=3){
            // staat de variabele al in de vector...?
            temp = false;
            for(int count = 0 ; count < orderedVector.size() ; count++ ){
                if(orderedVector.elementAt(count).equals(unorderedVector.elementAt(x+1))){
                    // Ja,
                    temp = true;
                    tempInt = count;
                }
            }
            if(temp){
                // variabele in vector
                // nieuwe value groter dan de huidige
                if(Double.parseDouble(orderedVector.elementAt(tempInt+1).toString()) < Double.parseDouble(unorderedVector.elementAt(x+2).toString()) ){
                    // save de waarde
                    orderedVector.remove(tempInt+1);
                    orderedVector.add(tempInt+1,unorderedVector.elementAt(x+2));
                }
            }
            else{
                // variabele niet in vector
                orderedVector.add(unorderedVector.elementAt(x+1));
                orderedVector.add(unorderedVector.elementAt(x+2));
            }

        }

		//gesorteerde vector terug geven
        return orderedVector;
    }


    public void ApplyRules() {
        fuzzyValues = new Vector();
        for (int x = 0; x < parser.GetVariables().size(); x++) {
            if (getWord(parser.GetVariables().elementAt(x).toString(), 2).
                equals("in")) {
                // START INITIALISATIE VOOR FLC
                variable = process.getVariable(getWord(parser.GetVariables().
                        elementAt(x).toString(), 0));
                if (printProgress) {
                    System.out.println("**Waarden voor fuzzyficatie: " +
                                       getWord(parser.GetVariables().elementAt(
                                               x).toString(), 0) +
                                       " Variabele waarde: " + variable);
                }

                // BEGIN FUZZIFICATIE
                fuzzyValues = fuzzy.calcUniverseValues(variable, getWord(parser.GetVariables().elementAt(x).toString(),0));
            }
        }
        if (false) {
            System.out.println("");
            for (int y = 0; y < fuzzyValues.size(); y++) {
				System.out.println("**Waarden na fuzzyficatie in de vector: " +
                                   fuzzyValues.elementAt(y));
            }
        }

        // BEGIN RULEMAKING
        Vector rules = parser.GetRules();
        for (int z = 0; z < rules.size(); z++) {
            analyseRule(rules.elementAt(z).toString());
        }

        if (false) {
            for (int y = 0; y < temp.size(); y++) {
                System.out.println("**Waarden na regeltoepassing in de vector: " +
                                   temp.elementAt(y).toString());
            }
        }

        temp = orderVector(temp);

        if (printProgress) {
            for (int y = 0; y < temp.size(); y++) {
                System.out.println("**Waarden in gesorteerde vector: " +
                                   temp.elementAt(y).toString());
            }
        }


        // BEGIN DEFUZZIFICATIE
        Vector defuzzyValues = defuzzy.DefuzzyVariables(temp);
        if (printProgress) {
            System.out.println("");
            for (int y = 0; y < defuzzyValues.size(); y++) {
				System.out.println("**Waarden na defuzzyficatie in de vector: " +
                                   defuzzyValues.elementAt(y).toString());
            }
            System.out.println("\n**Defuzzificatie: waarde van Tank-process: " +
                               Double.parseDouble(defuzzyValues.elementAt(
                                       defuzzyValues.size() - 1).toString()));
        }

        // SET VALUE IN PROCESS
        process.setVariable(defuzzyValues.elementAt(0).toString(),
                            Double.
                            parseDouble(defuzzyValues.elementAt(1).toString()));
    }

    private String getWord(String setstr, int nr) {
        int currentWord = 0;
        int i = 0;

        //spaties vervangen voor een [ of een ]
        setstr = setstr.replace('[', ' ');
        setstr = setstr.replace(']', ' ');
        setstr = setstr.trim();

        while (setstr.length() > 0) {
            if (i == setstr.length() || setstr.charAt(i) == '\n' ||
                setstr.charAt(i) == ' ' || setstr.charAt(i) == '\t') {
                //einde van huidige woord gevonden
                if (nr == currentWord) {
                    //huidige woord moet worden teruggegeven
                    return (setstr.substring(0, i)).trim();
                }
                //nog niet het goede woord, doorgaan met volgende woord zoeken
                setstr = (setstr.substring(i, setstr.length())).trim();
                i = 0;
                currentWord++;
            }
            i++;
        }
        return null;
    }
}
